package com.qire.manhua.view.comicReader;

import com.qire.common.collect.SafeIterableList;
import com.qire.common.function.Consumer;
import com.qire.common.function.Function;
import com.qire.manhua.view.comicReader.renderer.PictureResource;

import java.util.List;
import java.util.Objects;

/**
 * 安全图片资源列表,继承自安全遍历器列表，可以在多线程下安全遍历所有子元素不必担心多线程中操作remove或add操作导致数组长度变化而引发的异常问题，
 * 采用链表结构，保证在迭代过程中也能安全插入并且获得遍历的可能具体可查看 {@link SafeIterableList} 具体实现
 */
public class PictureSafeList extends SafeIterableList<PictureResource> {

    /**
     * 获取列表尾部的数据
     * @return
     */
    public PictureResource last() {
        return isEmpty() ? null : newest().value();
    }

    /**
     * 数据列表判断是否满足替换数据的条件
     * @param dstList
     * @return true 允许替换， false 不允许
     */
    public boolean allowReplace(List<PictureResource> dstList) {

        if(dstList == null || dstList.isEmpty())
            return false;

        if(isEmpty())
            return true;

        if(size() != dstList.size())
            return true;

        Node<PictureResource> firstNode = eldest();
        Node<PictureResource> endNode = newest();

        if(firstNode == null || !firstNode.value().equals(dstList.get(0)))
            return true;

        if(endNode == null || !endNode.value().equals(dstList.get(dstList.size() - 1)))
            return true;

        return false;
    }

    /**
     * 遍历所有图片资源并调用给定行为来处理资源。
     * @param action 指定行为
     */
    public void forEach(Consumer<PictureResource> action) {
        Objects.requireNonNull(action);
        for (Node<PictureResource> node : this) {
            action.accept(node.value());
        }
    }

    /**
     * 遍历列表查找到你需要的资源对象，并返回他的索引
     * @param action 比较行为，返回 true 表示发现并处理了，false 则表示忽略
     * @return
     */
    public int indexOf(Function<PictureResource, Boolean> action) {
        Objects.requireNonNull(action);
        int index = 0;
        for (Node<PictureResource> node : this) {
            if(action.apply(node.value())) {
                return index;
            }
            index++;
        }
        return -1;
    }

    /**
     * 遍历列表查找到你需要的资源对象
     * @param action 比较行为，返回 true 表示发现并处理了，false 则表示忽略
     * @return
     */
    public PictureResource findBy(Function<PictureResource, Boolean> action) {
        Objects.requireNonNull(action);
        for (Node<PictureResource> node : this) {
            if(action.apply(node.value())) {
                return node.value();
            }
        }
        return null;
    }

    /**
     * 填充一个列表，使用列表内容从 start 开始向 resourceArray 里填充 count 个内容。
     * 如果从 start 开始到 count 长度超过列表长度，则只渠道列表最后一个停止。
     * @param resourceArray 目标列表
     * @param start 起始点
     * @param count 填充个数
     */
    public void fillRange(PictureResource[] resourceArray, int start, int count) {
        // SafeIterableList 是一个安全可伸缩的列表，即允许在便利中改变长度，那么下面的遍历可能不稳定，会有增长或缩小的情况导致数据发生变化
        // 可以使用 for(node : this) 遍历 在循环内控制index的累加和退出。
        int end = Math.min(size(), start + count);

        for (int index = start; index < end; index++) {
            Node<PictureResource> node = get(index);
            if(node != null) {
                resourceArray[index - start] = node.value();
            }
        }
    }

}
